package com.ztools.pc.interceptor;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.ztools.common.model.pc.login.LoginToken;
import com.ztools.common.model.pc.sys.Permission;
import com.ztools.common.util.common.Result;
import com.ztools.common.util.common.ResultCode;
import com.ztools.common.util.common.TokenUtil;
import com.ztools.common.util.pc.AccessConfig;
import com.ztools.common.util.pc.TokenAuthorization;
import com.ztools.pc.async.AccessConfigAsync;
import com.ztools.pc.service.sys.RolePermissionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author:一口香菜
 * @Date: 2023/3/1  20:59
 * @Version 1.0
 * 拦截器
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    private static final String LOGIN_TOKEN = "seeTools-Token";
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private TokenUtil tokenUtil;
    @Resource
    private RolePermissionService rolePermissionService;
    @Resource
    private AccessConfigAsync accessConfigAsync;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 判断是否有权限注解
        TokenAuthorization tokenAuthorization = method.getAnnotation(TokenAuthorization.class);
        AccessConfig accessConfig = method.getAnnotation(AccessConfig.class);
        // 获取token
        String token = request.getHeader(LOGIN_TOKEN);
        if (accessConfig != null) {
            // 是否需要记录访问记录
            if (accessConfig.record()) {
                accessConfigAsync.accessRecord(request, method.getName());
            }
        }
        if (tokenAuthorization != null) {
            if (StrUtil.isNotEmpty(token)) {
                LoginToken loginToken = tokenUtil.get(token);
                if (loginToken != null) {
                    // 判断是否有权限注解
                    if (StringUtils.hasText(tokenAuthorization.value())) {
                        // 查询账号的权限
                        List<Permission> permissionList = rolePermissionService.findPerByRoleId(loginToken.getUserId());
                        // 判断是否有权限
                        List<Permission> dataList = permissionList.stream().filter(item -> item.getPath().equals(tokenAuthorization.value())).collect(Collectors.toList());
                        if (dataList.size() < 1) {
                            sendMessage(response, ResultCode.FAIL);
                            return false;
                        }
                    }
                    return true;
                }
            }
            sendMessage(response, ResultCode.LACKTOKEN);
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }


    private void sendMessage(HttpServletResponse response, ResultCode resultCode) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try {
            response.getWriter().write(JSON.toJSONString(Result.error(resultCode)));
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }

}
